home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_03_04
/
3n04052a
< prev
next >
Wrap
Text File
|
1992-02-09
|
19KB
|
630 lines
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=Begin Listing4-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/*****************************************************/
/* listmenu.c */
/* -- Implements a popup menu with a scrollable */
/* ListBox. */
/*****************************************************/
/*****************************************************/
/* Header files. */
/*****************************************************/
#include <windows.h>
#include "listmenu.h"
/*****************************************************/
/* Constants. */
/*****************************************************/
#define imdsNil -1 /* Undefined menu index. */
#define cbMenuMax 256 /* Max. length of MenuItem. */
#define szMenuClass "#32768" /* Menu classname. */
#define szListClass "ListBox" /* LBox classname. */
#define szFilter "LFilter" /* Filter classname. */
/*****************************************************/
/* Types. */
/*****************************************************/
typedef struct
{
int cidm; /* # items in menu. */
int dx, dy; /* Size of menu. */
int idm; /* Index in MenuBar. */
HMENU hmnu; /* Original popup menu. */
HWND hwnd; /* ListBox window. */
WORD rgidm[1]; /* MenuItem id array */
} MDS; /* Menu DeScriptor. */
typedef MDS FAR * LPMDS;
typedef HANDLE HMDS;
typedef HMDS FAR * LRGHMDS;
/*****************************************************/
/* Globals. */
/*****************************************************/
HANDLE hrghmds; /* Handle to array of menus. */
int cmds; /* Number of menus. */
int imdsDown; /* Dropped popup menu. */
HWND hwndMenu; /* Popup menu window. */
HWND hwndMain; /* App's main window. */
HMENU hmnuTop; /* App's MenuBar. */
FARPROC lpfnMenuFilter; /* Popup menu subclasser. */
FARPROC lpfnMenu; /* Popup menu window proc. */
FARPROC lpfnMain; /* App's main window proc. */
FARPROC lpfnMainFilter; /* Subclasser for above. */
FARPROC lpfnListFilter; /* Subclasser for ListBox. */
FARPROC lpfnList;
BOOL fButtonDown; /* Buttoned down in list? */
/*****************************************************/
/* Private Prototypes. */
/*****************************************************/
void CloseListMenu(void);
void DestroyMenuImds(int);
BOOL FAR PASCAL FEnumWnd(HWND, LONG);
void GetMdsImds(MDS *, int);
WORD IdmFromIidmImds(int, int);
int ImdsFromIdm(WORD);
LONG FAR PASCAL ListFilter(HWND, WORD, WORD, LONG);
LONG FAR PASCAL MainFilter(HWND, WORD, WORD, LONG);
LONG FAR PASCAL MenuFilter(HWND, WORD, WORD, LONG);
void RemoveListMenu(BOOL);
/*****************************************************/
/* Routines. */
/*****************************************************/
BOOL
FInitListMenu(BOOL fFirst, HWND hwnd)
/*****************************************************/
/* -- Initialize the list menu module. */
/* -- hwnd : Window containing MenuBar. */
/* -- szMenuList : Name of menu list of popups. */
/*****************************************************/
{
FARPROC lpfn; /* EnumWindows() callback. */
HANDLE hins; /* App's instance. */
WNDCLASS wcs; /* Our own ListBox class. */
hwndMain = hwnd;
if ((hmnuTop = GetMenu(hwnd)) == NULL)
return FALSE;
/* Get the popup menu handle so we can subclass */
/* it at will. */
hins = GetWindowWord(hwnd, GWW_HINSTANCE);
if ((lpfn = MakeProcInstance(FEnumWnd, hins)) ==
NULL)
return FALSE;
EnumWindows(lpfn, 0L);
FreeProcInstance(lpfn);
if (hwndMenu == NULL)
return FALSE;
lpfnMenu =
(FARPROC)GetWindowLong(hwndMenu, GWL_WNDPROC);
if ((lpfnMenuFilter = MakeProcInstance(
(FARPROC)MenuFilter, hins)) == NULL)
return FALSE;
/* Subclass the app's main window. */
lpfnMain =
(FARPROC)GetWindowLong(hwndMain, GWL_WNDPROC);
if ((lpfnMainFilter = MakeProcInstance(
(FARPROC)MainFilter, hins)) == NULL)
return FALSE;
SetWindowLong(hwndMain, GWL_WNDPROC,
(LONG)lpfnMainFilter);
/* Create a our version of the ListBox class. */
if (!GetClassInfo(NULL, szListClass, &wcs))
return FALSE;
lpfnList = (FARPROC)wcs.lpfnWndProc;
if (fFirst)
{
wcs.lpfnWndProc = ListFilter;
wcs.hInstance = hins;
wcs.lpszClassName = szFilter;
if (!RegisterClass(&wcs))
return FALSE;
}
imdsDown = imdsNil;
return TRUE;
}
BOOL FAR PASCAL
FEnumWnd(HWND hwnd, LONG lwp)
/*****************************************************/
/* -- EnumWindows() callback to get popup menu */
/* window handle. */
/*****************************************************/
{
char szBuf[40];
GetClassName(hwnd, szBuf, sizeof szBuf);
if (!lstrcmp(szBuf, szMenuClass))
{
hwndMenu = hwnd;
return FALSE;
}
return TRUE;
}
void
CloseListMenu(void)
/*****************************************************/
/* -- Close the list menu module. */
/*****************************************************/
{
int imds;
if (cmds == 0)
return; /* Nothing to do. */
/* Destroy all list menus. */
for (imds = 0; imds < cmds; imds++)
DestroyMenuImds(imds);
/* Remove filters. */
if (lpfnMenu != NULL)
{
if (IsWindow(hwndMenu))
SetWindowLong(hwndMenu, GWL_WNDPROC,
(LONG)lpfnMenu);
lpfnMenu = NULL;
}
if (lpfnMenuFilter != NULL)
{
FreeProcInstance(lpfnMenuFilter);
lpfnMenuFilter = NULL;
}
if (lpfnMain != NULL && IsWindow(hwndMain))
SetWindowLong(hwndMain, GWL_WNDPROC,
(LONG)lpfnMain);
if (lpfnMainFilter != NULL)
{
FreeProcInstance(lpfnMainFilter);
lpfnMainFilter = NULL;
}
/* Restore state and free menu table array. */
hmnuTop = NULL;
hwndMenu = hwndMain = NULL;
GlobalFree(hrghmds);
hrghmds = NULL;
cmds = 0;
}
BOOL
FAssignMenu(WORD idm, int dy)
/*****************************************************/
/* -- Assign a list menu to the given MenuItem. */
/* -- The strings and command values for the list */
/* menu are extracted from the given popup menu. */
/* -- Return TRUE for success, FALSE for failure. */
/* -- idm : MenuItem id. */
/* -- dy : Height of the menu. */
/*****************************************************/
{
int imds;
HMENU hmnu;
HMDS hmds = NULL;
LPMDS lpmds = NULL;
HDC hdc = NULL;
int iidm, cidm;
BOOL fVal = FALSE;
HANDLE hins;
/* See if a list menu for this popup already */
/* exists. If not, grow (or allocate if for the */
/* first time) the list menu table array. If */
/* a list menu already exists, destroy it, but */
/* reuse its slot in the array. */
if ((imds = ImdsFromIdm(idm)) == imdsNil)
{
/* Grow menu array. */
if (cmds == 0)
{
if ((hrghmds = GlobalAlloc(
GMEM_MOVEABLE | GMEM_ZEROINIT,
sizeof(HMDS))) == NULL)
goto FAssignMenuError;
cmds = 1;
imds = 0;
}
else
{
HANDLE hrghmdsNew;
imds = cmds++;
if ((hrghmdsNew = GlobalReAlloc(hrghmds,
cmds * sizeof(HMDS),
GMEM_MOVEABLE | GMEM_ZEROINIT))
== NULL)
goto FAssignMenuErro